package gui.typeEditors;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.JTextField;

import owg.util.Calc;


public abstract class NumberEditor<T extends Number> extends TypeEditor<T> implements ActionListener, FocusListener
	{
	static final long serialVersionUID = 2704835030524222886L;
	
	static final int DEFAULT_COLUMNS = 9;
	
	JTextField field;
	T value;
	boolean ignoreEvents = false;
	Color origcolor;
	
	T displayValueMultiplier;
	
	public NumberEditor(T initialValue, T displayValueMultiplier, int columns, boolean permitGrowing)
		{
		super();
		if(!permitGrowing)
			setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
		this.displayValueMultiplier = displayValueMultiplier;
		
		
		field = new JTextField();
		origcolor = field.getBackground();
		field.setColumns(columns);
		setValue(initialValue, false);
		add(field);
		field.addActionListener(this);
		field.addFocusListener(this);
		}
	@Override
	public void setFont(Font font)
	{
		super.setFont(font);
		if(field != null)//Gets called by super constructor... Otherwise field is always defined.
			field.setFont(font);
	}
	protected void setValue(T val, boolean fire)
		{
		T pVal = value;
		value = val;
		ignoreEvents = true;
		int ppos = field.getCaretPosition();
		field.setText(String.valueOf(mul(val, displayValueMultiplier)));
		field.setCaretPosition((int)Calc.limit(ppos, 0, field.getText().length()));
		ignoreEvents = false;
		if(fire && pVal != value)
			{
			fireActionEvents();
			flash(Color.GREEN);
			}
		}

	@Override
	public final void setValue(T val)
		{
		setValue(val, false);
		}

	@Override
	public void focusGained(FocusEvent e)
		{
		
		}

	@Override
	public void focusLost(FocusEvent e)
		{
		if(!ignoreEvents)
			parseValue();
		}

	@Override
	public void actionPerformed(ActionEvent e)
		{
		if(!ignoreEvents)
			parseValue();
		}

	private void parseValue()
		{
		try {
			setValue(div(parse(field.getText()), displayValueMultiplier), true);
			}
		catch(NumberFormatException e)
			{
			flash(Color.RED);
			setValue(value, false);
			}
		}

	protected abstract T div(T value, T divisor);
	protected abstract T mul(T value, T factor);

	protected abstract T parse(String text);

	synchronized void color(Color color)
		{
		field.setBackground(color);
		}

	private void flash(Color color)
		{
		color(color);
		flashThread(new Runnable(){public void run(){color(origcolor);}}, 33);
		}

	@Override
	public void setToolTipTextToSubComponents(String text)
		{
		field.setToolTipText(text);
		}

	@Override
	public void setSubComponentsEnabled(boolean en)
		{
		field.setEnabled(en);
		}
	}
